package com.coolingme.calculatebracket;

import com.coolingme.calculatebracket.expression.NumInterpreter;

import java.util.*;

/**
 * @author wangyue
 * @date 2022/12/25 16:52
 */
public class Calculator {

    private Stack<IArithmeticInterpreter> stack        = new Stack<>();
    private List<String>                  bracketList2 = new LinkedList();

    public Calculator(String expression) {
        this.parseBracket(expression);
    }

    private void parseBracket(String expression) {
        String[] elements = expression.split(" ");
        if (expression.contains("(")) {
            Stack<Integer> l = new Stack<Integer>();
            for (int i = 0; i < elements.length; i++) {
                bracketList2.add(elements[i]);
                if (OperatorUtil.isBracketLeftOperator(elements[i])) {
                    //将“（”入栈，记录“(”在list中的位置
                    l.push(bracketList2.size());
                } else if (OperatorUtil.isBracketRightOperator(elements[i])) {
                    int start = l.pop();
                    List ele = bracketList2.subList(start, bracketList2.size() - 1);
                    parse(ele);
                    //删除bracketList2中（）及里面的数据
                    while (bracketList2.size() >= start) {
                        bracketList2.remove(bracketList2.size() - 1);
                    }
                    //将（）内数据计算的结果转String加到list尾部
                    bracketList2.add(stack.pop().interpret() + "");
                }
            }
            //计算完括号内的数据再做最后计算
            parse(bracketList2);
        }
    }

    /**
     * 计算非（）内的数据
     *
     * @param elements
     */
    private void parse(List<String> elements) {
        IArithmeticInterpreter leftExpr, rightExpr;
        //用于存放加减的操作符
        Stack<String> operatorAD = new Stack<String>();
        for (int i = 0; i < elements.size(); i++) {
            String operator = elements.get(i);
            //乘除直接计算结果
            if (OperatorUtil.isOperatorMN(operator)) {
                leftExpr = this.stack.pop();
                rightExpr = new NumInterpreter(Integer.valueOf(elements.get(++i)));
                System.out.println("出栈: " + leftExpr.interpret() + " 和 " + rightExpr.interpret());
                this.stack.push(OperatorUtil.getInterpreter(leftExpr, rightExpr, operator));
                System.out.println("应用运算符: " + operator);
            } else if (OperatorUtil.isOperatorAS(operator)) {
                //加减优先入栈保存，等全部结束计算完乘除再处理
                //计算
                operatorAD.push(operator);
            } else {
                NumInterpreter numInterpreter = new NumInterpreter(Integer.valueOf(elements.get(i)));
                this.stack.push(numInterpreter);
                System.out.println("入栈: " + numInterpreter.interpret());
            }
        }

        if (!operatorAD.empty()) {
            rightExpr = this.stack.pop();
            //遍历操作符
            while (!operatorAD.empty()) {
                leftExpr = this.stack.pop();
                rightExpr = OperatorUtil.getInterpreter(leftExpr, rightExpr, operatorAD.pop());
            }
            this.stack.push(rightExpr);
        }
    }

    public int calculate() {
        return this.stack.pop().interpret();
    }
}

